package com.tarena.lbs.coupon.service.impl;

import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.coupon.api.pojo.param.UserCouponsParam;
import com.tarena.lbs.coupon.dao.repository.CouponRepository;
import com.tarena.lbs.coupon.dao.repository.UserCouponsRepository;
import com.tarena.lbs.coupon.enums.StockResultEnum;
import com.tarena.lbs.coupon.pojo.param.CouponParam;
import com.tarena.lbs.coupon.pojo.po.CouponPO;
import com.tarena.lbs.coupon.pojo.po.UserCouponsPO;
import com.tarena.lbs.coupon.pojo.query.UserCouponCodeQuery;
import com.tarena.lbs.coupon.pojo.query.UserCouponQuery;
import com.tarena.lbs.coupon.pojo.vo.CouponVO;
import com.tarena.lbs.coupon.pojo.vo.UserCouponsVO;
import com.tarena.lbs.coupon.service.CouponService;
import com.tarena.lbs.coupon.service.StockService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class CouponServiceImpl implements CouponService{
    
    @Autowired
    private CouponRepository couponRepository;
    
    @Autowired
    private UserCouponsRepository userCouponsRepository;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    //新增优惠券
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveCoupon(CouponParam couponParam) throws BusinessException {
        log.info("开始处理优惠券保存请求: {}", couponParam);
        // 参数校验
        if (couponParam == null) {
            log.warn("优惠券参数为空");
            throw new BusinessException(StockResultEnum.DATA_NOT_FIND);
        }
        
        // 构造优惠券实体
        CouponPO couponPO = new CouponPO();
        BeanUtils.copyProperties(couponParam, couponPO);
        log.info("转换后的优惠券实体: CouponPO:{}", couponPO);
        
        // 解析日期字符串
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            couponPO.setStartDate(sdf.parse(couponParam.getStartDate()));
            couponPO.setEndDate(sdf.parse(couponParam.getEndDate()));
        } catch (Exception ex) {
            //打印错误消息
            ex.printStackTrace();
        }
        if (couponParam.getId() != null) {
            // 新增
            couponPO.setCreateAt(new Date());
            couponPO.setUpdateAt(new Date());
            // 默认启用状态
            if (couponPO.getEnableStatus() == null) {
                couponPO.setEnableStatus(1); // 1表示启用
            }
            // 默认状态为有效
            if (couponPO.getStatus() == null) {
                couponPO.setStatus(1); // 1表示有效
            }
            // 设置必填字段的默认值
            if (couponPO.getBusinessId() == null) {
                // 实际项目中应从登录信息或上下文获取商家ID
                couponPO.setBusinessId(1); // 临时设置默认商家ID
            }
            
            // 执行数据库插入操作
            log.info("准备插入优惠券数据: 优惠券名称={}", couponPO.getCouponName());
            int result = couponRepository.insert(couponPO);
            log.info("插入优惠券结果: 影响行数{}", result);
            
            if (result > 0) {
                // 将新增的优惠券信息存储到Redis中，设置有效期
                String key = "coupon:" + couponPO.getId();
                redisTemplate.opsForValue().set(key, couponPO, 24, TimeUnit.HOURS); // 设置24小时过期
                log.info("成功插入优惠券并同步到Redis: ID={}", couponPO.getId());
            } else {
                log.warn("插入优惠券失败: 优惠券名称={}", couponPO.getCouponName());
                throw new BusinessException(StockResultEnum.SAVE_ERROR);
            }
        }
//        else {
//            // 更新
//            couponPO.setUpdateAt(new Date());
//            log.info("准备更新优惠券数据: CouponPO:{}", couponPO);
//            int result = couponRepository.updateById(couponPO);
//            log.info("更新优惠券结果: 影响行数{}", result);
            
//            if (result > 0) {
//                // 更新Redis中的优惠券信息
//                String key = "coupon:" + couponPO.getId();
//                redisTemplate.opsForValue().set(key, couponPO, 24, TimeUnit.HOURS); // 更新并重置过期时间
//                log.info("成功更新优惠券并同步到Redis: ID={}", couponPO.getId());
//            } else {
//                log.warn("更新优惠券失败，未找到对应的记录: ID={}", couponPO.getId());
//                throw new BusinessException(StockResultEnum.UPDATE_ERROR);
//            }
//        }
    }
    //领取优惠券
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void receiveCoupon(UserCouponsParam param) throws BusinessException {
        log.debug("用户领取优惠券: {}", param);
        
        // 1. 参数校验
        if (param == null) {
            throw new BusinessException(StockResultEnum.DATA_NOT_FIND);
        }
        if (param.getUserId() == null) {
            throw new BusinessException(StockResultEnum.USER_ID_NULL);
        }
        if (param.getCouponId() == null) {
            throw new BusinessException(StockResultEnum.COUPON_ID_NULL);
        }
        
        // 2. 检查优惠券是否存在
        CouponPO couponPO = couponRepository.selectById(param.getCouponId());
        if (couponPO == null) {
            throw new BusinessException(StockResultEnum.COUPON_NOT_FIND);
        }
        
        // 3. 检查优惠券状态是否有效
        if (couponPO.getStatus() != 1 || couponPO.getEnableStatus() != 1) {
            throw new BusinessException(StockResultEnum.COUPON_INVALID);
        }
        
        // 4. 检查优惠券时间是否在有效期内
        Date now = new Date();
//        log.debug("检查优惠券时间: 优惠券ID={}, 当前时间={}, 开始时间={}, 结束时间={}",
//                 param.getCouponId(), now, couponPO.getStartDate(), couponPO.getEndDate());
//
//        if (couponPO.getStartDate() != null && now.before(couponPO.getStartDate())) {
//            log.warn("优惠券尚未开始: 当前时间{}早于开始时间{}", now, couponPO.getStartDate());
//            throw new BusinessException(StockResultEnum.COUPON_TIME_INVALID);
//        }
//
//        if (couponPO.getEndDate() != null && now.after(couponPO.getEndDate())) {
//            log.warn("优惠券已过期: 当前时间{}晚于结束时间{}", now, couponPO.getEndDate());
//            throw new BusinessException(StockResultEnum.COUPON_TIME_INVALID);
//        }
        
        // 5. 检查用户是否已经领取过该优惠券
        int count = userCouponsRepository.countByUserIdAndCouponId(param.getUserId(), param.getCouponId());
        log.debug("用户{}是否领取过优惠券{}: 查询结果:{}条", param.getUserId(), param.getCouponId(), count);
        if (count > 0  && couponPO.getUsageLimit() != null) {
            throw new BusinessException(StockResultEnum.COUPON_ALREADY_RECEIVED);//抛出优惠券已领取异常
        }
        
        // 6. 使用Redis检查并扣减库存
        String stockKey = "coupon:stock:" + param.getCouponId();
        Object stockObj = redisTemplate.opsForValue().get(stockKey);
        Integer stock = null;
        
        if (stockObj != null) {
            stock = Integer.valueOf(stockObj.toString());
        } else {
            // 如果Redis中没有库存信息，从数据库查询
            // 注意：这里简化处理，实际应该有查询优惠券库存的方法
            // 此处假设优惠券的maxUsageLimit就是总库存
            stock = couponPO.getMaxUsageLimit();
            if (stock != null) {
                redisTemplate.opsForValue().set(stockKey, stock, 24, TimeUnit.HOURS);
            }
        }
        
        if (stock != null && stock <= 0) {
            throw new BusinessException(StockResultEnum.COUPON_STOCK_EMPTY);
        }
        
        // 7. 扣减库存
        Long decrementResult = redisTemplate.opsForValue().decrement(stockKey);
        if (decrementResult == null || decrementResult < 0) {
            // 库存不足，回滚
            redisTemplate.opsForValue().increment(stockKey);
            throw new BusinessException(StockResultEnum.COUPON_STOCK_EMPTY);
        }
        
        try {
            // 8. 生成优惠券码
            String couponCode = UUID.randomUUID().toString().replace("-", "").substring(0, 16).toUpperCase();
            
            // 9. 保存用户优惠券信息
            UserCouponsPO userCouponsPO = new UserCouponsPO();
            BeanUtils.copyProperties(param, userCouponsPO);
            userCouponsPO.setStatus(0); // 0表示未使用
            userCouponsPO.setCreateAt(now);
            userCouponsPO.setUpdateAt(now);
            userCouponsPO.setCouponCode(couponCode);
            userCouponsPO.setCouponType(couponPO.getCouponType());
            userCouponsPO.setCouponValue(couponPO.getDiscountValue());
            
            // 如果参数中没有活动ID和店铺ID，设置默认值
            if (userCouponsPO.getActivityId() == null) {
                userCouponsPO.setActivityId(1); // 默认为1，实际应该从优惠券或参数中获取
            }
            if (userCouponsPO.getShopId() == null) {
                userCouponsPO.setShopId(1); // 默认为1，实际应该从商家信息中获取
            }
            
            int insertResult = userCouponsRepository.insert(userCouponsPO);
            if (insertResult <= 0) {
                throw new BusinessException(StockResultEnum.COUPON_RECEIVE_FAIL);
            }
            
            log.info("用户领取优惠券成功: 用户ID={}, 优惠券ID={}, 优惠券码={}", 
                     param.getUserId(), param.getCouponId(), couponCode);
        } catch (Exception e) {
            // 发生异常，回滚库存
            redisTemplate.opsForValue().increment(stockKey);
            log.error("用户领取优惠券失败: {}", e.getMessage(), e);
            throw new BusinessException(StockResultEnum.COUPON_RECEIVE_FAIL);
        }
    }
    
    //查看优惠券码的二维码图片
    @Override
    public UserCouponsVO receiveDetail(UserCouponCodeQuery query) throws BusinessException {
        // 参数校验
        if (query == null || query.getCouponCode() == null || query.getCouponCode().isEmpty()) {
            throw new BusinessException(StockResultEnum.DATA_NOT_FIND);
        }
        
        // 模拟从数据库或Redis中查询优惠券信息
        // 实际项目中这里应该调用DAO层查询数据库
        UserCouponsVO vo = new UserCouponsVO();
        vo.setCouponCode(query.getCouponCode());
        vo.setUserId(query.getUserId());
        
        // 生成二维码URL(模拟)
        vo.setCouponUrl("http://localhost:8080/qrcode/" + query.getCouponCode());
        
        return vo;
    }
//查看用户领取优惠券列表
    @Override
    public PageResult<UserCouponsVO> receiveList(UserCouponQuery couponQuery) {
        log.debug("用户领取优惠券列表功能参数:{}" , couponQuery);
        PageResult<UserCouponsVO> pageResult = couponRepository.receiveList(couponQuery);
        return pageResult;
    }
//查看优惠券详情
    @Override
    public CouponVO detail(Integer id) {
        // 查询优惠券信息
        CouponPO couponPO = couponRepository.selectById(id);
        if (couponPO == null) {
            log.debug("优惠券不存在: ID={}", id);
            return null;
        }
        
        // 转换为VO对象
        CouponVO couponVO = new CouponVO();
        BeanUtils.copyProperties(couponPO, couponVO);
        return couponVO;
    }
}